问题描述(难度中等-1195)
Write a program that outputs the string representation of numbers from 1 to n, however:
- If the number is divisible by 3, output “fizz”.
- If the number is divisible by 5, output “buzz”.
- If the number is divisible by both 3 and 5, output “fizzbuzz”.
For example, for n = 15
, we output: 1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz
.
Suppose you are given the following code:
1 | class FizzBuzz { |
Implement a multithreaded version of FizzBuzz
with four threads. The same instance of FizzBuzz
will be passed to four different threads:
- Thread A will call
fizz()
to check for divisibility of 3 and outputsfizz
. - Thread B will call
buzz()
to check for divisibility of 5 and outputsbuzz
. - Thread C will call
fizzbuzz()
to check for divisibility of 3 and 5 and outputsfizzbuzz
. - Thread D will call
number()
which should only output the numbers.
方法一:using volatile
通过定义volatile变量flag,以循环自检的方式执行。这里总结下这种方法的通用范式:
1 | while(trure){ |
上面的范式可以通用,但是可能会导致TLP问题。
1 | package P1195; |
方法二:using synchronized
通过对象提供的基本操作等待/通知范式,等待通知需要定义两个基本操作一个生产一个消费:
1 | private void consumer(){ |
1 | private void producer(){ |
如果要进行范式的循环,在范式外面加一层循环,于是范式演变成:
1 | private void consumer(){ |
利用上面的范式,我们可以看到关键是要确定两步:
- 1.循环次数
- 2.变量的等待条件
1 | package P1195; |
方法三:using lock
这里维护多个等待队列貌似没有意义。
1 | package P1195; |
方法四:using atomic
利用atomic提供的封装函数,实际上利用cas实现原子写操作。
1 | import java.util.ConcurrentModificationException; |
总结
通过循环自检或者等待通知的方式实现。